<template>
  <el-form
      :model="review"
      ref="review"
      label-position="right"
      label-width="120px"
      size="small"
      class="form"
      :rules="rules"
  >
    <el-form-item prop="title" label="影评标题">
      <el-input type="text" v-model="review.title" clearable/>
    </el-form-item>
    <el-form-item prop="author" label="影评作者">
      <el-input type="text" v-model="review.author" clearable/>
    </el-form-item>
    <el-form-item prop="rating" label="影评评分">
      <el-input type="text" v-model="review.rating" clearable/>
    </el-form-item>
    <el-form-item prop="source" label="影评来源">
      <el-select v-model="review.source">
        <el-option value="douban" label="豆瓣"></el-option>
        <el-option value="imdb" label="IMDb"></el-option>
      </el-select>
    </el-form-item>
    <el-form-item prop="created_at" label="创建日期">
      <el-date-picker type="date" v-model="review.created_at" clearable/>
    </el-form-item>
    <el-form-item prop="useful_count" label="点赞数">
      <el-input type="text" v-model="review.useful_count"/>
    </el-form-item>
    <el-form-item prop="content" label="影评内容">
      <el-input
          type="textarea"
          v-model="review.content"
          :autosize="{ minRows: 2, maxRows: 6}"
      />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="handleSubmit" style="width: 120px">提交</el-button>
      <el-button @click="handleCancel" style="width: 120px">取消</el-button>

    </el-form-item>
  </el-form>
</template>

<script>
  export default {
    name: "ReviewUpdate",
    props: {
      data: {
        type: Object,
        required: true,
        default() {
          return {}
        }
      },
    },
    data() {
      const requireChecker = ({ message = "该项必须填写", trigger = "blur" } = {}) => ({
        required: true,
        message,
        trigger
      });

      const isEmpty = value => value === "";

      const lenChecker = (len, trigger = "blur") => {
        return { min: 0, max: len, message: `最多输入${len}个字符`, trigger };
      };

      const decimalChecker = (len, trigger = "blur") => {
        const validator = (rule, value, callback) => {
          if (isEmpty(value)) {
            return callback();
          }
          const parsed = String(value);
          const dotPos = parsed.indexOf(".");
          if (dotPos < 0) {
            return callback();
          }
          const decimalLength = parsed.length - 1 - dotPos;
          if (decimalLength > len) {
            return callback(new Error(`最多可输入${len}位小数`));
          }
          callback();
        };
        return { validator, trigger };
      };

      const numberChecker = (trigger = "blur") => {
        const validator = (rule, value, callback) => {
          if (isEmpty(value)) {
            return callback();
          }
          const isNumber = !isNaN(Number(value));
          if (!isNumber) {
            return callback(new Error("请输入数字"));
          }
          callback();
        };
        return { validator, trigger };
      };

      const rangeChecker = (min, max, trigger = "blur") => {
        const validator = (rule, value, callback) => {
          if (isEmpty(value)) {
            return callback();
          }
          const parsed = Number(value);
          if (max < parsed || min > parsed) {
            return callback(new Error(`请输入${min}-${max}之间的数字`));
          }
          callback();
        };
        return {
          validator,
          trigger
        };
      };

      const intChecker = (trigger = "blur") => {
        const validator = (rule, value, callback) => {
          if (isEmpty(value)) {
            return callback();
          }
          const isInt = /^-?[1-9]\d*$|0/.test(value);
          if (!isInt) {
            return callback(new Error("请输入整数"));
          }
          callback();
        };
        return { validator, trigger };
      };



      return {
        review: {
          id: "",
          title: "",
          author: "",
          created_at: "",
          source: "",
          content: "",
          useful_count: "",
          subject_id: "",
          rating: "",
        },
        rules: {
          title: [requireChecker(), lenChecker(128)],
          author: [requireChecker(), lenChecker(32)],
          rating: [
            requireChecker(),
            numberChecker(),
            rangeChecker(0, 9.9),
            decimalChecker(1)
          ],
          useful_count: [requireChecker(), numberChecker(), intChecker()],
          content: [requireChecker()],
          created_at: [
            requireChecker({ trigger: "change" }),
          ],
          source: [requireChecker({ trigger: 'change' })]
        }
      };
    },
    methods: {
      async handleSubmit() {
        if (!(await this.validate())) {
          return;
        }
        this.$emit('submit', this.handleBeforeSubmit(this.review))
      },
      handleCancel() {
        this.$emit('cancel')
      },
      validate() {
        return new Promise(async resolve => {
          try {
            await this.$refs.review.validate();
            resolve(true);
          } catch (e) {
            resolve(false);
          }
        });
      },
      handleBeforeSubmit(review) {
        const origin = { ...review };
        origin.title = origin.title.trim()
        origin.content = origin.content.trim()
        origin.created_at = new Date(origin.created_at).toJSON()
        origin.rating = +origin.rating
        origin.useful_count = +origin.useful_count
        return origin;
      },
      handleBeforeReceive(review) {
        const origin = {
          ...review
        };
        origin.created_at = origin.created_at && new Date(origin.created_at) || ""
        return origin
      },
    },
    computed: {
      isUpdate() {
        return !!this.review.id;
      }
    },
    watch: {
      data: {
        immediate: true,
        handler(v) {
          this.review = this.handleBeforeReceive(v)
          this.$nextTick(() => {
            this.$refs.review && this.$refs.review.clearValidate()
          })
        }
      },
    }
  };
</script>

<style lang="scss" scoped>
  .form {
    width: 480px;
    margin: 0 auto;
  }
</style>